package com.sc.nft.admin.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.admin.request.*;
import com.sc.nft.annotation.SysMemberLogin;
import com.sc.nft.entity.CollecionLinkContrastRecords;
import com.sc.nft.entity.vo.metaWalletDTO.AdminGetLinkCollectionInfoVO;
import com.sc.nft.entity.vo.metaWalletDTO.AdminLinkCollectionPageVO;
import com.sc.nft.entity.vo.metaWalletDTO.OfferToMetaCollectionPageDTO;
import com.sc.nft.entity.vo.metaWalletDTO.ToMetaCollectionPageDTO;
import com.sc.nft.entity.vo.metaWalletDTO.request.NotLinkCollectionPageRequest;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.DigitalCollectionService;
import com.sc.nft.service.MetaWalletService;
import com.sc.nft.sup.MetaPage;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import com.sc.nft.util.EncryptionUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/meta/wallet")
@Api(tags = "后台跨链模块")
public class AdminMetaWallerController {

    private final DigitalCollectionService digitalCollectionService;
    private final MetaWalletService metaWalletService;
    private final Redisson redisson;

    @PostMapping(value = "/getNotLinkCollectionPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取未关联的藏品集合(钱包藏品)", notes = "获取未关联的藏品集合(钱包藏品)", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<OfferToMetaCollectionPageDTO> getNotLinkCollectionPage(@Valid @RequestBody NotLinkCollectionPageRequest request) throws Exception {
        return metaWalletService.getNotLinkCollectionPage(request);
    }

    @PostMapping(value = "/linkCollection", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "与钱包藏品关联", notes = "与钱包藏品关联", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result linkCollection(@Valid @RequestBody LinkCollectionRequest request) {
        CollecionLinkContrastRecords collecionLinkContrastRecords = BeanUtil.copyProperties(request, CollecionLinkContrastRecords.class);
        collecionLinkContrastRecords.setLinkIssuePrice(request.getLinkIssuedPrice());
        metaWalletService.linkCollection(collecionLinkContrastRecords);
        return Result.success();
    }

    @PostMapping(value = "/getLinkCollectionInfo", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取关联钱包藏品信息", notes = "获取关联藏品信息", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public Result<AdminGetLinkCollectionInfoVO> getLinkCollectionInfo(@Valid @RequestBody IdRequest request) {
        return Result.success(metaWalletService.getLinkCollectionInfo(request.getId()),AdminGetLinkCollectionInfoVO.class);
    }

    @PostMapping(value = "/getLinkCollectionPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取关联钱包藏品列表", notes = "与钱包藏品关联", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @SysMemberLogin
    public PageResult<AdminLinkCollectionPageVO> getLinkCollectionPage(@Valid @RequestBody AdminLinkCollectionPageRequest request) {
        return PageResult.success(metaWalletService.getLinkCollectionPage(request.getCollectionName(), request.getLinkCollectionName(),request.toMp()));
    }


    @PostMapping(value = "/transferCollectonFromMetaWallet", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "接收玛特钱包的藏品(钱包调用)", notes = "接收玛特钱包的藏品", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result transferCollectonFromMetaWallet(@Valid @RequestBody TransferCollectonFromMetaWalletRequest request) throws IllegalAccessException {
        EncryptionUtil.decryptObject(request);

        RLock lock = redisson.getLock(StrUtil.format("{}{}:{}", RedisKeyEnum.TRANSFER_COLLECTION_FROM_META_WALLET_LOCK.getKey(), request.getCollectionId(), request.getTokenId()));
        try {
            boolean res = lock.tryLock(10, TimeUnit.SECONDS);
            if (res) {
                metaWalletService.transferCollectonFromMetaWallet(Long.valueOf(request.getCollectionId()), Integer.valueOf(request.getTokenId()), request.getToUserAddress(), request.getFromUserAddress(),request.getFromUserNickName());
            }else{
                return Result.fail("请稍后重试!");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new GlobalRunTimeException("系统超时");
        } finally {
            lock.unlock();
        }

        return Result.success();
    }

    @PostMapping(value = "/checkUserAddrIsExist", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "校验用户地址是否存在", notes = "校验用户地址是否存在", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result checkUserAddrIsExist(@Valid @RequestBody CheckUserAddrIsExistRequest request) throws IllegalAccessException {
        EncryptionUtil.decryptObject(request);
        return Result.success(metaWalletService.checkUserAddrIsExist(request.getUserAddr()));
    }

    @PostMapping(value = "/checkCollecton", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "校验藏品是否可以转增", notes = "校验藏品是否可以转增", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result checkCollecton(@Valid @RequestBody CheckCollectonRequest request) throws IllegalAccessException {
        EncryptionUtil.decryptObject(request);
        metaWalletService.checkCollecton(Long.valueOf(request.getCollectionId()), JSONUtil.toList(request.getTokenIds(), Integer.class));
        return Result.success();
    }


    @PostMapping(value = "/toWalletNotLinkCollectionPage", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "获取未关联的藏品列表", notes = "校验用户地址是否存在", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    public MetaPage<ToMetaCollectionPageDTO> toWalletNotLinkCollectionPage(@Valid @RequestBody NotLinkCollectionPageRequest request) throws IllegalAccessException {
        EncryptionUtil.decryptObject(request);
        Page<ToMetaCollectionPageDTO> page = metaWalletService.toWalletNotLinkCollectionPage(request.getDaoName(), request.getCollectionName(), request.toMp());
        for (ToMetaCollectionPageDTO record : page.getRecords()) {
            EncryptionUtil.encryptObject(record);
        }
        return MetaPage.success(page);
    }

}
